package com.sentiment.nlpalgo.method;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sentiment.nlpalgo.bean.Depparser;
import com.sentiment.nlpalgo.bean.Double2;
import com.sentiment.nlpalgo.bean.Keywords;
import com.sentiment.nlpalgo.bean.Ner;
import com.sentiment.nlpalgo.bean.Tag;
import com.sentiment.nlpalgo.bean.Taglist;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/*
 * @author liaozhenlin,hanchaojun
 * @email 939899727@qq.com
 * 
 */

/*
 * 通过调用相关接口，获得文本分析结果
 * 单文本分析
 */

public class AlgoHttp {
	private static final Logger LOG = LoggerFactory.getLogger(AlgoHttp.class);

	public static final String X_TOKEN = "ouFY-S7c.3495.9mpe6aMSZIoM";
	public static final String SENTIMENT_URL = "http://api.bosonnlp.com/sentiment/analysis"; // 情感分析链接，通用类
	public static final String SENTIMENT_AUTO = "?auto"; // 情感分析链接，追加汽车类
	public static final String SENTIMENT_KITCHEN = "?kitchen"; // 情感分析链接，追加厨具类
	public static final String SENTIMENT_FOOD = "?food"; // 情感分析链接，追加餐饮类
	public static final String SENTIMENT_NEWS = "?news"; // 情感分析链接，追加新闻类
	public static final String SENTIMENT_WEIBO = "?weibo"; // 情感分析链接，追加微博类
	public static final String NER_URL = "http://api.bosonnlp.com/ner/analysis"; // 命名实体识别链接
	public static final String DEPPARSER_URL = "http://api.bosonnlp.com/depparser/analysis"; // 依存文法分析链接
	public static final String KEYWORDS_URL = "http://api.bosonnlp.com/keywords/analysis"; // 关键字分析链接

	public static final String SUGGEST_URL = "http://api.bosonnlp.com/suggest/analysis"; // 词义联想链接
	public static final String TAG_URL = "http://api.bosonnlp.com/tag/analysis?"; // 分词和词性标记链接
	public static final String CLASSIFY_URL = "http://api.bosonnlp.com/classify/analysis"; // 新闻分类链接
																							//

	/**
	 * 情感分析函数，调用通用类链接 list：输入的字符串数组 relist:返回对应句的情感倾向的数组 tag代表输入数据的类别，例如新闻类，食物类
	 */
	public ArrayList<Double2> sentiment(List<String> list, String tag) {
		Double2 data;
		ArrayList<Double2> relist = new ArrayList<Double2>();
		String url = SENTIMENT_URL;
		if ("auto".equals(tag)) {
			url = url + SENTIMENT_AUTO;
		} else if ("kitchen".equals(tag)) {
			url = url + SENTIMENT_KITCHEN;
		} else if ("food".equals(tag)) {
			url = url + SENTIMENT_FOOD;
		} else if ("news".equals(tag)) {
			url = url + SENTIMENT_NEWS;
		} else if ("weibo".equals(tag)) {
			url = url + SENTIMENT_WEIBO;
		}
		String jsonString = htPostArrList(list, url);
		if (jsonString == null) {
			return null;
		}
		JSONArray array = JSONArray.fromObject(jsonString);
		Iterator it = array.iterator();
		while (it.hasNext()) {
			JSONArray temp = (JSONArray) it.next();
			data = new Double2(temp.getDouble(0), temp.getDouble(1));
			relist.add(data);
		}
		return relist;
	}

	/*
	 * 命名实体识别函数 list：输入的字符串数组 relist:返回相关名词和所属实体的数组
	 */
	public ArrayList<Ner> nerment(List<String> list) {
		ArrayList<Ner> relist = new ArrayList();
		Ner ner;
		String jsonString = htPostArrList(list, NER_URL);
		if (jsonString == null) {
			return null;
		}
		JSONArray array = JSONArray.fromObject(jsonString);
		Iterator it = array.iterator();
		while (it.hasNext()) {
			JSONObject obj = (JSONObject) it.next();
			int left, right;
			JSONArray arr2 = obj.getJSONArray("entity");
			JSONArray arr4 = obj.getJSONArray("word");
			Iterator it2 = arr2.iterator();
			while (it2.hasNext()) {
				JSONArray arr3 = (JSONArray) it2.next();
				left = arr3.getInt(0);
				right = arr3.getInt(1);
				String name = "";
				String type = arr3.getString(2);
				for (int i = left; i < right; i++) {
					name = name + arr4.getString(i);
				}
				ner = new Ner(name, type);
				relist.add(ner);
			}
		}
		return relist;
	}

	/*
	 * 新闻分类函数，调用通用类链接 relist:返回对应句的新闻类别数组 对应于NlpEnum里面的classSelect枚举类 需要输出时调用即可
	 */
	public ArrayList<Integer> classify(List<String> list) {
		ArrayList<Integer> relist = new ArrayList<Integer>();
		String jsonString = htPostArrList(list, CLASSIFY_URL);
		if (jsonString == null) {
			return null;
		}
		JSONArray array = JSONArray.fromObject(jsonString);
		Iterator it = array.iterator();
		int score = 0;
		while (it.hasNext()) {
			int temp = (Integer) it.next();
			relist.add(temp);
		}
		System.out.println(relist);
		return relist;

	}

	/*
	 * 依存文法分析函数 将输入的字符串数组转换成依存成分 保存在Depparser中
	 */
	public ArrayList<Depparser> depparser(List<String> list) {
		ArrayList<Depparser> relist = new ArrayList();
		Depparser dep;
		String jsonString = htPostArrList(list, DEPPARSER_URL);
		if (jsonString == null) {
			return null;
		}
		JSONArray array = JSONArray.fromObject(jsonString);
		Iterator it = array.iterator();
		while (it.hasNext()) {
			JSONObject temp = (JSONObject) it.next();
			JSONArray arr = temp.getJSONArray("word");
			JSONArray arr2 = temp.getJSONArray("tag");
			JSONArray arr3 = temp.getJSONArray("head");
			JSONArray arr4 = temp.getJSONArray("role");
			Iterator it2 = arr.iterator();
			int score = 0;
			while (it2.hasNext()) {
				String word = (String) it2.next();
				String tag = (String) arr2.get(score);
				int head = (int) arr3.get(score);
				String role = (String) arr4.get(score);
				score++;
				dep = new Depparser(word, tag, head, role);
				relist.add(dep);
			}

		}
		return relist;
	}

	/**
	 * 关键字分析函数 将输入的字符串数组转换成关键字成分 权重和单词 保存在Keywords中
	 */
	public ArrayList<Keywords> keywords(List<String> list) {
		ArrayList<Keywords> relist = new ArrayList();
		Keywords keywords;
		String jsonString = htPostArrList(list, KEYWORDS_URL);
		System.out.println("--" + jsonString);
		if (jsonString == null) {
			return null;
		}
		JSONArray array = JSONArray.fromObject(jsonString);
		Iterator it = array.iterator();
		while (it.hasNext()) {
			JSONArray arr = (JSONArray) it.next();
			Iterator it2 = arr.iterator();
			while (it2.hasNext()) {
				JSONArray temp = (JSONArray) it2.next();
				double weight = temp.getDouble(0);
				String word = temp.getString(1);
				keywords = new Keywords(weight, word);
				relist.add(keywords);
			}

		}
		return relist;
	}

	/*
	 * 词义联想函数 返回给定的某个词的相识词语 改函数http正文内容为非JSON型数据 调用特殊函数:htPostSingleWord
	 */
	public ArrayList<Keywords> suggest(String str) {
		ArrayList<Keywords> keylist = new ArrayList();
		Keywords keywords;
		String jsonString = htPostSingleWord(str, SUGGEST_URL);
		if (jsonString == null) {
			return null;
		}
		JSONArray array = JSONArray.fromObject(jsonString);
		Iterator it = array.iterator();
		while (it.hasNext()) {
			JSONArray arr = (JSONArray) it.next();
			double weight = (double) arr.get(0);
			String word = arr.getString(1).replaceAll("/n", "");
			keywords = new Keywords(weight, word);
			keylist.add(keywords);
		}
		// System.out.println(keylist);
		return keylist;
	}

	/*
	 * 分词及词性标记函数 返回字符串数组的分词及对应标记
	 */
	public ArrayList<Taglist> tag(List<String> list) {
		Tag tag = new Tag();
		Ner ner;
		ArrayList<Ner> nerlist;
		ArrayList<Taglist> taglists = new ArrayList();
		String url = TAG_URL + tag.toString();
		String jsonString = htPostArrList(list, url);
		if (jsonString == null) {
			return null;
		}
		System.out.println(jsonString);
		JSONArray arr = JSONArray.fromObject(jsonString);
		Iterator it = arr.iterator();
		while (it.hasNext()) {
			JSONObject obj = (JSONObject) it.next();
			JSONArray arr2 = obj.getJSONArray("word");
			JSONArray arr3 = obj.getJSONArray("tag");
			Iterator it2 = arr2.iterator();
			int index = 0;
			nerlist = new ArrayList();
			while (it2.hasNext()) {
				String word = (String) it2.next();
				String ta = (String) arr3.get(index);
				index++;
				ner = new Ner(word, ta);
				nerlist.add(ner);
			}
			Taglist taglist = new Taglist(nerlist);
			taglists.add(taglist);
		}
		System.out.println(taglists);
		return taglists;
	}

	public static void main(String[] args) {
		AlgoHttp algo = new AlgoHttp();
		ArrayList<String> list = new ArrayList();
		list.add("开心呢");
		list.add("傻逼");
		// list.add("你是个傻逼成都上院");
		algo.sentiment(list, "auto");
		// algo.nerment(list);
		// algo.depparser(list);
		// algo.keywords(list);
		// algo.suggest("粉丝");
		// algo.tag(list);
		// algo.classify(list);
	}

	/*
	 * 该函数使用HttpClient进行网络资源访问 list： 输入的数据数组，String类型 urlString ：地址
	 */
	public String htPostArrList(List<String> list, String urlString) {

		String jsonString = null;
		HttpClient client = new DefaultHttpClient(); // 生成一个HttpClient对象
		HttpPost httpPost = new HttpPost(urlString); // 采用post方法传输数据。
														// urlString为一个具体地址的url
		httpPost.addHeader("Content-Type", "application/json"); // 添加Http协议的Header
		httpPost.addHeader("Accept", "application/json");
		httpPost.addHeader("X-Token", X_TOKEN); // ?为一系列的字符组成，是API的密钥

		String body = JSONArray.fromObject(list).toString();
		httpPost.setEntity(new StringEntity(body.toString(), "UTF-8"));
		HttpResponse response; // 定义HttpResponse
		try {
			response = client.execute(httpPost); // 执行post请求
			int code = response.getStatusLine().getStatusCode(); // 获取返回code
			if (code == 200) { // 成功
				HttpEntity httpEntity = response.getEntity();
				BufferedReader bufferedReader = null;
				StringBuilder entityStringBuilder = new StringBuilder();
				if (httpEntity != null) {

					bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"),
							8 * 1024);
					String line = null;
					while ((line = bufferedReader.readLine()) != null) {
						entityStringBuilder.append(line);
					}

					jsonString = entityStringBuilder.toString();

				}
			} else {
				LOG.error("网络链接出错，请查看相关代码等" + code);
			}
		} catch (ConnectException e) {
			LOG.error(e.toString());
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return jsonString;
	}

	public static String string2Unicode(String string) {

		StringBuffer unicode = new StringBuffer();

		for (int i = 0; i < string.length(); i++) {

			// 取出每一个字符
			char c = string.charAt(i);

			// 转换为unicode
			unicode.append("\\u" + Integer.toHexString(c));
		}

		return "\"" + unicode.toString() + "\"";
	}

	/*
	 * 针对单个单词发送请求
	 */
	public String htPostSingleWord(String word, String urlString) {

		String jsonString = "";
		HttpClient client = new DefaultHttpClient(); // 生成一个HttpClient对象
		HttpPost httpPost = new HttpPost(urlString); // 采用post方法传输数据。
														// urlString为一个具体地址的url
		httpPost.addHeader("Content-Type", "application/json"); // 添加Http协议的Header
		httpPost.addHeader("Accept", "application/json");
		httpPost.addHeader("X-Token", X_TOKEN); // 为一系列的字符组成，是API的密钥

		httpPost.setEntity(new StringEntity(string2Unicode(word), "UTF-8")); // 转换为Unicode编码
		HttpResponse response; // 定义HttpResponse
		try {
			response = client.execute(httpPost); // 执行post请求
			int code = response.getStatusLine().getStatusCode(); // 获取返回code
			if (code == 200) { // 成功
				HttpEntity httpEntity = response.getEntity();
				BufferedReader bufferedReader = null;
				StringBuilder entityStringBuilder = new StringBuilder();
				if (httpEntity != null) {

					bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "UTF-8"),
							8 * 1024);
					String line = null;
					while ((line = bufferedReader.readLine()) != null) {
						entityStringBuilder.append(line);
					}

					jsonString = entityStringBuilder.toString();

				}
			} else {
				System.out.println("网络链接出错，请查看相关代码等" + code);
				return null;
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return jsonString;
	}

}
